<template>
  <div class="subject_container">
    <!-- <div class="cover"></div> -->
    <div class="subject">
      <div class="subject_content">
        <span>连一连，生活中常见的标识和它们代表的意思。</span>
      </div>
      <div class="next_subject_btn" v-if="isHaveRight" @click="toNext"></div>
    </div>
    <div class="option_list" id="container">
      <div class="list">
        <div
          class="list_item"
          v-for="(item, index) in topData"
          :key="index"
          :id="'up-' + index"
        >
          <img :src="item.imgs" alt="" />
        </div>
      </div>
      <div class="list">
        <div
          class="list_bottom"
          v-for="(item, index) in bottomList"
          :id="'below-' + index"
          :key="index"
        >
          {{ item.name }}
        </div>
      </div>
    </div>
    <FullScreenTip
      :tipMsg="tipMsg"
      :tipType="tipType"
      v-if="tipMsg"
      @close="closeTip"
    />
  </div>
</template>
<script setup>
import { jsPlumb } from "jsplumb";
import { ref, onMounted, nextTick } from "vue";
import { useRouter } from "vue-router";
import RIGHTTIPMP3 from "@/assets/audio/right_tip.mp3";
import WRONGTIPMP3 from "@/assets/audio/wrong_tip.mp3";
import FullScreenTip from "@/Components/FullScreenTip/Index.vue";
import { topData, bottomList, answer } from "./CONST.js";

const tipMsg = ref();
const tipType = ref(false);
const router = useRouter();
const isHaveRight = ref(false);
const rightTipAudio = new Audio(RIGHTTIPMP3);
const wrongTipAudio = new Audio(WRONGTIPMP3);

const instance = ref(null);

const init = () => {
  instance.value = jsPlumb.getInstance({
    // 创建一个新的 jsPlumb 实例，并将其赋值给 instance.value
    Container: "container",
    // 指定 jsPlumb 操作的容器元素 ID 为 "container"
    Connector: "Straight", // 设置连线的样式为直线
    // 修改为可分离，确保连线能正常创建
    ConnectionsDetachable: false, // 允许已创建的连线被分离
    DeleteEndpointsOnDetach: false, // 当连线被分离时，不删除端点
    Detachable: true, // 允许连线被分离
    isReattach: false,
    draggable: false,
    // 设置连线的默认样式
    PaintStyle: {
      strokeWidth: 3,
      stroke: "#64C556",
      dashstyle: "solid",
      outlineStroke: "transparent",
      outlineWidth: 5,
    },
    // 设置鼠标悬停在连线上时的样式
    HoverPaintStyle: {
      strokeWidth: 3,
      stroke: "#64C556",
      dashstyle: "solid",
      outlineStroke: "transparent",
      outlineWidth: 5,
    },
    // 设置连线端点的类型为圆点，半径为 20 像素
    Endpoint: ["Rectangle", { width: 10, height: 10 }],
    EndpointOptions: {
      detachable: false, // 防止断开连接
      draggable: false, // 防止拖拽
    },
    anchor: [0, 1, 0, 0],
    anchors: [
      // 定义源端的矩形锚点并添加偏移量
      // ["RightMiddle", 0, -50], // 使用内置锚点并添加偏移量
      // "LeftMiddle", // 目标端使用内置锚点
    ],
    // 设置端点的填充颜色为透明
    EndpointStyle: { fill: "transparent" },
  });
};

// 设置所有元素的连线源和目标
const setContainer = () => {
  instance.value.batch(() => {
    for (let i = 0; i < topData.length; i++) {
      initLeaf(`up-${i}`);
    }
    for (let j = 0; j < bottomList.length; j++) {
      initLeaf(`below-${j}`);
    }
  });
};
// 存储已链接的元素 ID
const connectedElements = ref(new Set());
// 验证连线是否合法（上下元素连线且元素未被连接过）。
const setRule = () => {
  // 添加连接验证逻辑
  instance.value.bind("beforeDrop", function (connInfo) {
    const sourceId = connInfo.sourceId;
    const targetId = connInfo.targetId;
    // 验证元素是否已经连接过
    const isConnected =
      connectedElements.value.has(sourceId) ||
      connectedElements.value.has(targetId);
    if (isConnected) {
      return false;
    }

    // 验证是否是 up 与 below 链接
    const isUpBelowLink =
      (sourceId.startsWith("up-") && targetId.startsWith("below-")) ||
      (sourceId.startsWith("below-") && targetId.startsWith("up-"));
    if (!isUpBelowLink) {
      return false;
    }

    if (sourceId.startsWith("up-")) {
      const topIndex = sourceId.split("-").pop();
      const bomIndex = targetId.split("-").pop();
      chooseOption(topIndex, bomIndex, sourceId, targetId);
    } else {
      const topIndex = sourceId.split("-").pop();
      const bomIndex = targetId.split("-").pop();
      chooseOption(bomIndex, topIndex, sourceId, targetId);
    }

    instance.value.unmakeSource(sourceId);
    instance.value.unmakeSource(targetId);
    connectedElements.value.add(sourceId);
    connectedElements.value.add(targetId);
    return true;
  });
};
// 设置元素为连线源或移除连线源能力，并设置元素为连线目标
const initLeaf = (id) => {
  const elem = document.getElementById(id);
  // 若元素未链接，则允许其作为连线源
  if (!connectedElements.value.has(id)) {
    instance.value.makeSource(elem, {
      anchor: ["Bottom", "Top"],
      allowLoopback: false,
      maxConnections: -1,
    });
  } else {
    // 若元素已链接，移除其作为连线源的能力
    // instance.value.removeSource(elem);
  }
  instance.value.makeTarget(elem, { anchor: ["Bottom", "Top"] });
};

onMounted(() => {
  nextTick(() => {
    jsPlumb.ready(function () {
      // 初始化 jsPlumb 创立 jsPlumb 实例
      init();
      // 设置能够为连线终点和连线起点的元素
      setContainer();
      // 在连线事件中 只容许连贯相邻的列表 不能跨列表连贯
      setRule();
      jsPlumb.fire("jsPlumbDemoLoaded", instance.value);
    });
  });
});

// 存放选中正确的元素
const selectAll = ref([]);
const chooseOption = (top, bom, sourceId, targetId) => {
  isHaveRight.value = true;
  if (answer[top] !== bom) {
    tipMsg.value = "请再试一次";
    tipType.value = false;
    wrongTipAudio.play();
    nextTick(() => {
      const connections = instance.value.getConnections(); // 获取所有连接的数组
      connections.forEach(function (conn) {
        if (conn.sourceId === sourceId && conn.targetId === targetId) {
          conn.setPaintStyle({ stroke: "red", strokeWidth: 3 });
        }
      });
    });
  } else {
    selectAll.value.push(top);
    rightTipAudio.play();
    // if (selectAll.value.length === 9) {
    //   isHaveRight.value = true;
    //   rightTipAudio.play();
    // }
  }
};
/**
 * 下一题
 */
const toNext = () => {
  if (selectAll.value.length !== 9) {
    tipMsg.value = "还有别的链接项，再连一连。";
    tipType.value = true;
    wrongTipAudio.play();
    return;
  }

  isHaveRight.value = false;
  router.replace({
    path: "/Second",
  });
};
/**
 * 关闭提示弹窗
 */
const closeTip = () => {
  if (tipMsg.value === "还有别的链接项，再连一连。") {
    tipMsg.value = null;
    return;
  }
  const connections = instance.value.getConnections(); // 获取所有连接的数组
  connections.forEach(function (connection, index) {
    if (index === connections.length - 1) {
      const { sourceId, targetId } = connection;
      connectedElements.value.delete(sourceId);
      connectedElements.value.delete(targetId);
      instance.value.deleteConnection(connection); // 删除找到的连接
    }
  });
  tipMsg.value = null;
  nextTick(() => {
    setContainer();
  });
};
</script>
<style lang="less" scoped>
.subject_container {
  position: relative;
}

.subject {
  position: absolute;
  top: 64px;
  left: 195px;
  display: flex;
  align-items: center;
  width: 1530px;
  height: 118px;
  border-radius: 40px;
  background: #ffffff96;
  box-sizing: border-box;
  border: 9px solid #ffd153;

  .subject_content {
    display: flex;
    align-items: center;
    margin-left: 80px;
    margin-right: 95px;
    width: 1170px;
    height: 72px;

    > span {
      font-size: 43px;
      letter-spacing: normal;
      font-weight: 600;
      color: #000000;
    }
  }

  .next_subject_btn {
    cursor: pointer;
    width: 116px;
    height: 99px;
    background-image: url(@/assets/icon/next_subject.png);
    background-repeat: no-repeat;
    background-size: 100% 100%;
  }
}

.option_list {
  position: absolute;
  left: 110px;
  top: 423.16px;
  width: 1789px;
  height: 314px;
  .list {
    width: 100%;
    &:first-child {
      width: 1731px;
      margin-left: 50px;
      margin-bottom: 135px;
    }
    .list_item {
      display: inline-block;
      width: 120px;
      height: 120px;
      line-height: 120px;
      margin-right: 70px;
      img {
        width: 100%;
        height: 100%;
      }
      &:last-child {
        margin-right: 0px;
      }
    }
    .list_bottom {
      display: inline-block;
      height: 67px;
      line-height: 60px;
      border-radius: 271px;
      padding: 6px 18px;
      background: #fffde9;
      box-shadow: 0px 7px 0px 0px #d0b05f;
      font-family: FZLanTingYuanS-R-GB;
      font-size: 34px;
      font-weight: normal;
      text-align: center;
      letter-spacing: 0.09em;
      font-variation-settings: "opsz" auto;
      margin-right: 6px;
      &:last-child {
        margin-right: 0px;
      }
    }
  }
}
</style>
